package com.ninong.ker.admin.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ninong.ker.admin.domain.User;
import com.ninong.ker.admin.mapper.DicMapper;
import com.ninong.ker.admin.mapper.LoginMapper;
import com.ninong.ker.admin.rest.vo.MenuVO;
import com.ninong.ker.admin.service.LoginService;
import com.ninong.ker.admin.service.dto.UserDTO;
import com.ninong.ker.common.auth.JwtProperties;
import com.ninong.ker.common.auth.SecurityAdmin;
import com.ninong.ker.common.exception.CmdException;
import com.ninong.ker.common.response.CmdResponse;
import com.ninong.ker.common.tools.CmdAdminTools;
import com.ninong.ker.common.tools.RedisUtils;
import com.ninong.ker.common.tools.enums.BusinessEnum;
import com.ninong.ker.common.user.OnlineUser;

import cn.hutool.crypto.SecureUtil;

/**
 * 
 * @author 鸠摩智
 * @date 2020年12月3日 上午11:10:05
 */
@Service
public class LoginServiceImpl extends ServiceImpl<LoginMapper, User> implements LoginService {

	private static final String BUTTON = "button";
	private static final String MENU = "menu";
	private static final String PARENT = "0";
	@Autowired
	private RedisUtils redisUtils;
	@Autowired
	private SecurityAdmin securityAdmin;
	@Autowired
	private JwtProperties properties;
	@Autowired
	private DicMapper dicMapper;

	@Override
	public CmdResponse login(UserDTO user) throws Exception {		
		if(!redisUtils.haskey(user.getUuid())) {
			throw new CmdException(BusinessEnum.VERIFICATION_CODE_EXPIRED);
		}
		// 查询验证码
		String code = redisUtils.get(user.getUuid()).toString();
		// 清除验证码
		redisUtils.del(user.getUuid());
		if (StringUtils.isBlank(code)) {
			throw new CmdException(BusinessEnum.VERIFICATION_CODE_ERROR);
		}
		if (StringUtils.isBlank(user.getCode()) || !user.getCode().equalsIgnoreCase(code)) {
			throw new CmdException(BusinessEnum.VERIFICATION_CODE_ERROR);
		}
		QueryWrapper<User> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("user_name", user.getUserName());
		queryWrapper.eq("deleted", true);
		User login = baseMapper.selectOne(queryWrapper);
		if (ObjectUtils.isEmpty(login)) {
			throw new CmdException(BusinessEnum.USER_NAME_AND_PASSWORD);
		} else {
			if (!login.getEnabled()) {

				throw new CmdException(BusinessEnum.USER_ENABLED);
			}
		}
		user.setPassword(CmdAdminTools.decryptByPrivateKey(properties.privateKey, user.getPassword()));
		String password = SecureUtil.md5(login.getSalt() + user.getPassword());
		if (!StringUtils.equals(login.getPassword(), password)) {
			throw new CmdException(BusinessEnum.USER_NAME_AND_PASSWORD);
		}
		Map<String, Object> param = Maps.newHashMap();
		param.put("id", login.getId());
		param.put("type", BUTTON);
		List<String> roles = baseMapper.findAuthorities(param);
		// 生成令牌
		String token = securityAdmin.createToken(JSONObject.toJSONString(login));
		Map<String, Object> responseMap = Maps.newHashMap();
		login.setPassword(null);
		responseMap.put("user", login);
		responseMap.put("dics", dicMapper.getDicTree());
		OnlineUser  online= new OnlineUser(roles,login.getId(), login.getDeptId(), login.getDeptName(), login.getUserName(), login.getNickName(), login.getPhone(), login.getEmail(),new Date());
		redisUtils.set(properties.getOnline() + token, JSONObject.toJSON(online) , properties.getValidity() / 1000);
		responseMap.put("token", token);
		CmdResponse response = new CmdResponse();
		response.setData(responseMap);
		return response;
	}

	@Override
	public List<MenuVO> listMenus(String token) {
		OnlineUser user = securityAdmin.currentUser(token);
		Map<String, Object> param = Maps.newHashMap();
		param.put("uid", user.getId());
		param.put("pid", PARENT);
		param.put("type", MENU);
		List<MenuVO> vos = baseMapper.getMenus(param);
		return vos;
	}

	@Override
	public List<String> listInfo(String token) {
		OnlineUser user = securityAdmin.currentUser(token);
		Map<String, Object> param = Maps.newHashMap();
		param.put("id", user.getId());
		param.put("type", BUTTON);
		List<String> roles = baseMapper.findAuthorities(param);
		return roles;
	}

	@Override
	public PageInfo<JSONObject> listOnline(UserDTO dto) {
		List<String> onlines = redisUtils.findkeysForPage(properties.getOnline() + "*", dto.getCurrentPage(),
				dto.getPageSize());
		ArrayList<JSONObject> list = Lists.newArrayList();
		onlines.forEach(cmd -> {
		 JSONObject json = JSONObject.parseObject(redisUtils.get(cmd).toString());
		 json.put("id", cmd);
		 list.add(json);
		});
		long total = redisUtils.lGetListSize(properties.getOnline() + "*");
		PageInfo<JSONObject>  info = new PageInfo<JSONObject>();
		info.setList(list);
		info.setTotal(total);
		return info;
	}

	@Override
	public void removeOnline(String[] keys) {
		List<String> list = Arrays.asList(keys);
		list.forEach(key -> {
			redisUtils.del(key);
		});
	}


}
